//
//  BaseLabel.m
//  InTubePro
//
//  Created by seven on 2020/1/11.
//  Copyright © 2020 seven. All rights reserved.
//

#import "BaseLabel.h"
@interface BaseLabel(){
    UILongPressGestureRecognizer *_copyGesture;
}
@end
@implementation BaseLabel

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.verticalAlignment = ITVerticalAlignmentMiddle;
    }
    return self;
}
 
- (void)setVerticalAlignment:(ITVerticalAlignment)verticalAlignment {
    _verticalAlignment = verticalAlignment;
    [self setNeedsDisplay];
}
 
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
    CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
    switch (self.verticalAlignment) {
        case ITVerticalAlignmentTop:
            textRect.origin.y = bounds.origin.y;
            break;
        case ITVerticalAlignmentBottom:
            textRect.origin.y = bounds.origin.y + bounds.size.height - textRect.size.height;
            break;
        case ITVerticalAlignmentMiddle:
            // Fall through.
        default:
            textRect.origin.y = bounds.origin.y + (bounds.size.height - textRect.size.height) / 2.0;
    }
    return textRect;
}
 
-(void)drawTextInRect:(CGRect)requestedRect {
    CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
    actualRect.origin.x += _leftOffset - _rightOffset;

    if (_topOffset != 0) {
        actualRect.origin.y += _topOffset;
    }
    [super drawTextInRect:actualRect];
}



- (CGSize)fitWidth:(CGFloat)width{
    return [self fitSize:CGSizeMake(width, CGFLOAT_MAX)];
}
- (CGSize)fitHeight:(CGFloat)height{
    return [self fitSize:CGSizeMake(CGFLOAT_MAX, height)];
}
- (CGSize)fitSize:(CGSize)size{
    CGSize theSize = [self sizeThatFits:size];
    /*
    self.preferredMaxLayoutWidth = size.width;
    CGSize theSize = [self intrinsicContentSize];
     //*/
    if (size.width < size.height) {
        theSize.width = size.width;
    }else {
        theSize.height = size.height;
    }
    self.size = theSize;
    return self.size;
}

#pragma mark - copy
- (void)setSupportCopyAction:(BOOL)supportCopyAction{
    if (_supportCopyAction == supportCopyAction) return;
    _supportCopyAction = supportCopyAction;
    _copyGesture.enabled = _supportCopyAction;
    if (_supportCopyAction) {
        [self attachTapHandler];
    }
}

- (BOOL)canBecomeFirstResponder{
    return YES;
}

// 可以响应的方法
//此方法中只相应了复制和粘贴两个方法，也就是弹出的面板中只有复制和粘贴两个按钮。
//其它方法都返回No代表禁止，面板内不会出现相应的按钮。
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    return (action == @selector(copy:));
}
//针对于响应方法的实现,点击copy按钮时调用此方法
- (void)copy:(id)sender{
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];
    pboard.string = self.text;
}

//有了以上三个方法，我们就能处理copy和paste了，当然，在能接收到事件的情况下：
//UILabel默认是不接收事件的，我们需要自己添加touch事件
- (void)attachTapHandler{
    self.userInteractionEnabled = YES;  //用户交互的总开关
    if (_copyGesture == nil) {
        _copyGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
        [self addGestureRecognizer:_copyGesture];
    }
}

//接下来，我们需要处理这个tap，以便让菜单栏弹出来：
- (void)handleTap:(UIGestureRecognizer*) recognizer{
    //if判断是为了保证长按手势只执行一次
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        [self becomeFirstResponder];
        [[UIMenuController sharedMenuController] setTargetRect:self.bounds inView:self];

        //UIMenuItem *addItem = [[UIMenuItem alloc] initWithTitle:LocalTitle(@"report") action:@selector(addAction:)];
        [[UIMenuController sharedMenuController] setMenuVisible:YES animated: YES];
    }
}
- (void)setCustomAction:(CustomAction)customAction{
    _customAction = customAction;
    self.userInteractionEnabled = _customAction != nil;
}
#pragma mark - 点击文字

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch *touch = touches.anyObject;
    CGPoint pt = [touch locationInView:self];
    [self textAttributesAtPoint:pt];
}

- (NSDictionary *)textAttributesAtPoint:(CGPoint)pt{
    
    UILabel *lab = self;
    // Locate the attributes of the text within the label at the specified point
    NSDictionary* dictionary =nil;

    // First, create a CoreText framesetter
    CTFramesetterRef framesetter =CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)lab.attributedText);

    CGMutablePathRef framePath =CGPathCreateMutable();

    CGPathAddRect(framePath,NULL,CGRectMake(0,0, lab.frame.size.width, lab.frame.size.height));

    // Get the frame that will do the rendering.

    CFRange currentRange =CFRangeMake(0,0);

    CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath,NULL);

    CGPathRelease(framePath);

    // Get each of the typeset lines

    NSArray *lines = (__bridge id)CTFrameGetLines(frameRef);

    CFIndex linesCount = [lines count];

    CGPoint *lineOrigins = (CGPoint*)malloc(sizeof(CGPoint) * linesCount);

    CTFrameGetLineOrigins(frameRef,CFRangeMake(0, linesCount), lineOrigins);

    CTLineRef line =NULL;

    CGPoint lineOrigin = CGPointZero;

    // Correct each of the typeset lines (which have origin (0,0)) to the correct orientation (typesetting offsets from the bottom of the frame)

    CGFloat bottom = lab.frame.size.height;

    for(CFIndex i =0; i < linesCount; ++i) {

        lineOrigins[i].y = lab.frame.size.height- lineOrigins[i].y;

        bottom = lineOrigins[i].y;
    }

    // Offset the touch point by the amount of space between the top of the label frame and the text

    pt.y -= (lab.frame.size.height- bottom)/2;

    // Scan through each line to find the line containing the touch point y position
    
    NSTextAlignment alignment = NSTextAlignmentLeft;
    if (self.attributedText) {
        alignment = self.attributedText.alignment;
    }else {
        alignment = lab.textAlignment;
    }
    
    for (CFIndex i =0; i < linesCount; ++i) {

        line = (__bridge CTLineRef)[lines objectAtIndex:i];

        lineOrigin = lineOrigins[i];

        CGFloat descent, ascent;

        CGFloat width = CTLineGetTypographicBounds(line, &ascent, &descent,nil);

        if (pt.y < (floor(lineOrigin.y) + floor(descent))) {

            // Cater for text alignment set in the label itself (not in the attributed string)

            if(alignment == NSTextAlignmentCenter) {

                //pt.x-= (lab.frame.size.width- width)/2;

            }else if(alignment==NSTextAlignmentRight) {

                //pt.x-= (lab.frame.size.width- width);
            }

            // Offset the touch position by the actual typeset line origin. pt is now the correct touch position with the line bounds

            pt.x-= lineOrigin.x;

            pt.y-= lineOrigin.y;

            // Find the text index within this line for the touch position

            CFIndex i = CTLineGetStringIndexForPosition(line, pt);

            // Iterate through each of the glyph runs to find the run containing the character index

            NSArray* glyphRuns = (__bridge id)CTLineGetGlyphRuns(line);

            CFIndex runCount = [glyphRuns count];

            for(CFIndex run=0; run < runCount; run++){

                CTRunRef glyphRun = (__bridge CTRunRef)[glyphRuns objectAtIndex:run];

                CFRange range = CTRunGetStringRange(glyphRun);

                if(i >= range.location && i <= range.location+range.length) {
                    
                    dictionary = (__bridge NSDictionary*)CTRunGetAttributes(glyphRun);
                    NSMutableDictionary *tmp = [NSMutableDictionary dictionaryWithDictionary:dictionary];
                    tmp[@"range"] = [NSValue valueWithRange:NSMakeRange(range.location, range.length)];
                    dictionary = tmp;
                    if (self.customAction) {
                        self.customAction(dictionary, cat_tap);
                    }
                    break;
                }
            }
            if (dictionary) {
                break;
            }
        }
    }
    
    free(lineOrigins);
    
    CFRelease(frameRef);
    
    CFRelease(framesetter);
    
    return dictionary;
}

@end


@implementation UILabel (Shadow)

- (void)setShadow{
    [self setShadowWithColor:ColorWithHexAplha(0x121212, 0.7)];
}

- (void)setShadowWithColor:(UIColor *)color{
    
    self.layer.shadowOffset = CGSizeMake(0, 1);
    self.layer.shadowOpacity = 1.0f;
    self.layer.shadowRadius = 1;
    self.layer.shadowColor = color.CGColor;
}

@end
